//! get remote version or using given version
//! get local version
//! download zip if not exist, download temp first then move, for download error
//! unzip zip to install dir
//! add env if not exist
//! reboot exe for updateing self
//! 
//! 
//! auto update using crontab(linux) / schtasks(windows)
//! 

use std::{env::current_dir, fs::{create_dir, remove_dir_all, remove_file, rename}, path::{Path, PathBuf}, thread::sleep, time::Duration};



use clap::Parser;
use wtask_base::{app::{get_wtask_data_dir, get_wtask_root_dir}, cmd::{file_unzip, start_exe_spawn}, error::WResult, export::{log_debug, log_info}, logs::LogArgs, req::{download_file, download_txt}, update::{WTASK_FILE_INSTSLL_PREFIX, dir_update}};

use crate::{add_envs, stop_exe};



#[derive(Debug, Clone, Parser)]
#[command(author, version, about="wTask安装及卸载", help_template = "\
{before-help}
{about-with-newline}
{usage-heading} {usage}
{all-args}{after-help}

Version: {version}
Author: {author-with-newline}
")]
pub struct CMDArgs {
    /// 指定安装的版本，否则从远程加载最新版本
    #[arg(long)]
    pub ver: Option<String>,

    /// 从指定文件夹加载安装文件
    #[arg(long)]
    pub dir: Option<String>,

    /// 如果指定文件夹加载安装文件，则是否删除该文件夹
    #[arg(long, requires = "dir")]
    pub del: bool,
    
    /// 远程仓库路径
    #[arg(long, default_value = "LonlyWinter/wTask")]
    pub repo: String,

    /// 程序安装路径，默认为用户家目录下的wtask文件夹
    #[arg(long)]
    pub root: Option<String>,
    
    #[command(flatten)]
    pub log_args: LogArgs,
}

pub fn get_remove_version(args: &CMDArgs) -> WResult<String> {
    if let Some(version) = &args.ver {
        Ok(version.to_owned())
    } else {
        let url = format!("https://api.github.com/repos/{}/releases/latest", args.repo);
        log_debug!("Remote version: {url}");
        let v = download_txt(&url, None)?;
        let res = v.split_once("v0.0.").unwrap().1.split_once("\"").unwrap().0;
        Ok(res.to_owned())
    }
}

pub fn get_install_file(args: &CMDArgs) -> WResult<PathBuf> {
    let version = args.ver.clone().expect("No remote version found");
    let file_name = format!("{}.{}.zip", WTASK_FILE_INSTSLL_PREFIX.as_str(), version);
    
    let dir = if let Some(dir) = &args.dir {
        PathBuf::from(dir)
    } else {
        current_dir()?
    };
    let p_final = dir_update()?.join(&file_name);
    let p = dir.join(&file_name);
    if p.exists() {
        rename(&p, &p_final)?;
    }
    if (!p_final.is_file()) || (!p_final.exists()) {
        let url = format!("https://github.com/{}/releases/download/v0.0.{}/{}.zip", args.repo, version, WTASK_FILE_INSTSLL_PREFIX.as_str());
        let p_temp = get_wtask_data_dir("temp", true)?.join(&file_name);
        log_info!("Downloading file: {:?} => {:?} ...", &url, &p_temp);
        download_file(&url, None, &p_temp)?;
        rename(&p_temp, &p_final)?;
    }
    log_info!("Get file: {:?}", &p_final);
    Ok(p_final)
}


fn unzip_install_file(p: &Path) -> WResult<()> {
    let dir = get_wtask_root_dir();
    if !dir.exists() {
        create_dir(&dir)?;
    }
    log_info!("Unziping file: {:?} => {:?} ...", p, &dir);
    file_unzip(p, &dir)?;
    Ok(())
}


fn shutdown_exe() -> WResult<()> {
    for exe in ["wtask_machine", "wtask_web", "wtask_bridge"] {
        log_info!("Stop exe: {exe} ...");
        let _ = stop_exe(exe);
    }
    sleep(Duration::from_secs(3));
    Ok(())
}

fn start_exe() -> WResult<()> {
    let dir = get_wtask_root_dir();
    
    let dir_file = dir.join("bin");

    log_info!("Starting wtask_machine ...");
    start_exe_spawn(&dir, vec![
        dir_file.join("wtask_machine").to_string_lossy().to_string(),
        "--noterminal".to_owned()
    ])?;
    
    log_info!("Starting wtask_web ...");
    start_exe_spawn(&dir, vec![
        dir_file.join("wtask_web").to_string_lossy().to_string(),
    ])?;

    log_info!("Starting wtask_bridge ...");
    start_exe_spawn(&dir, vec![
        dir_file.join("wtask_bridge").to_string_lossy().to_string(),
        "--noterminal".to_owned()
    ])?;

    sleep(Duration::from_secs(3));
    Ok(())
}


pub fn install_all(file_install: &Path) -> WResult<()> {
    shutdown_exe()?;
    unzip_install_file(file_install)?;
    add_envs()?;
    start_exe()?;
    Ok(())
}

pub fn uninstall_all() -> WResult<()> {
    let dir = get_wtask_root_dir();
    for n in ["bin", "LICENSE"] {
        let p = dir.join(n);
        if p.is_dir() {
            remove_dir_all(p)?;
        } else {
            remove_file(p)?;
        }
    }

    Ok(())
}